package com.yunchang.spring.visitor.core.utils;

import com.yunchang.spring.visitor.core.invoker.DefaultServiceInvoker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 支持类型转换的工具类
 */
public abstract class TypeUtil {

    private static final Logger log = LoggerFactory.getLogger(TypeUtil.class);

    /**
     * 将String字符串转为指定类型的值.
     *
     * @param value     String字符串
     * @param fieldType 指定类型
     * @return 返回转换后的值，如果转换失败，则抛出IllegalArgumentException异常
     * @throws IllegalArgumentException 如果传入fieldType不支持转化，则抛出异常
     */
    public static Object parseValue(String value, Class<?> fieldType) {
        if (value == null) {
            return null;
        }
        if (fieldType == String.class) {
            return value;
        } else if (fieldType == int.class || fieldType == Integer.class) {
            return Integer.parseInt(value);
        } else if (fieldType == short.class || fieldType == Short.class) {
            return Short.parseShort(value);
        } else if (fieldType == long.class || fieldType == Long.class) {
            return Long.parseLong(value);
        } else if (fieldType == float.class || fieldType == Float.class) {
            return Float.parseFloat(value);
        } else if (fieldType == double.class || fieldType == Double.class) {
            return Double.parseDouble(value);
        } else if (fieldType == boolean.class || fieldType == Boolean.class) {
            return Boolean.parseBoolean(value);
        } else if (fieldType.isEnum()) {
            // 枚举类型自动转型，这里是遍历所有的枚举对象，和所给值相同则返回
            Object[] enumConstants = fieldType.getEnumConstants();
            for (Object enumConstant : enumConstants) {
                if (enumConstant.toString().equals(value)) {
                    return enumConstant;
                }
            }
        } else if (Date.class.isAssignableFrom(fieldType)) {
            long timeStamp = 0;
            if (isNumber(value)) {
                // 字符串为纯数字时间戳
                timeStamp = Long.parseLong(value);
            } else {
                // 字符串为"yyyy-MM-dd日期格式
                try {
                    timeStamp = new SimpleDateFormat("yyyy-MM-dd").parse(value).getTime();
                } catch (ParseException e) {
                    log.error("" + e);
                }
            }
            try {
                return fieldType.getConstructor(long.class).newInstance(timeStamp);
            } catch (Exception e) {
                log.error("" + e);
            }
        } else {
            try {
                Object obj = fieldType.newInstance();
                if (obj instanceof DefaultServiceInvoker.TypeConverter) {
                    DefaultServiceInvoker.TypeConverter converter = (DefaultServiceInvoker.TypeConverter) obj;
                    // 自定义类型，调用自定义参数类型转化的方法
                    return converter.convert(value);
                }
            } catch (InstantiationException e) {
                log.error("TypeConverter InstantiationException " + fieldType.getName(), e);
            } catch (IllegalAccessException e) {
                log.error("TypeConverter IllegalAccessException" + fieldType.getName(), e);
            }
        }
        throw new IllegalArgumentException(String.format("Not support type %s", fieldType.getClass()));
    }

    private static boolean isNumber(String str) {
        if (StringUtils.isEmpty(str)) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断方法是否被子类覆盖。
     * 该方法会判断父类
     *
     * @param dist       子类
     * @param root       父类。如果传入null，那只比较子类和上一级父类的方法覆盖情况。
     * @param methodName 方法名
     * @param params     方法参数
     * @return 如果被覆盖，返回true；否则返回false
     */
    public static boolean isOverride(Class dist, Class root, String methodName, Class... params) {
        boolean result = false;
        if (root == null) {
            root = dist.getSuperclass();
        }
        while (dist != root && !result) {
            // 递归检查，子类的上一级父类是否覆盖该方法
            result = checkIsOverride(dist, methodName, params);
            dist = dist.getSuperclass();
        }
        return result;
    }

    private static boolean checkIsOverride(Class dist, String methodName, Class[] params) {
        for (Method methodSon : dist.getDeclaredMethods()) {
            if (methodName.equals(methodSon.getName()) && methodSon.getParameterCount() == params.length) {
                Class[] bc = methodSon.getParameterTypes();
                for (int i = 0; i < bc.length; i++) {
                    if (!bc[i].equals(params[i])) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    }

}
